package com.bub.pay.core.interceptor.mybatis;

import com.bub.pay.core.base.BaseDomain;
import com.bub.pay.framework.common.entity.model.UserSession;
import com.bub.pay.framework.common.util.ContextHolder;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.ibatis.binding.BindingException;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.Properties;

@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class CommonFillInterceptor implements Interceptor {

    private static final Logger log = LoggerFactory.getLogger(CommonFillInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        SqlCommandType sqlCommandType = null;
        for (Object arg : args) {
            if (arg instanceof MappedStatement) {
                sqlCommandType = ((MappedStatement) arg).getSqlCommandType();
                if (sqlCommandType != SqlCommandType.INSERT && sqlCommandType != SqlCommandType.UPDATE)
                    break;
                continue;
            }
            Class baseEntityClass = null;
            Object sourceParam = arg;
            if (arg instanceof BaseDomain || arg instanceof MapperMethod.ParamMap) {
                if (arg instanceof MapperMethod.ParamMap) {
                    try {
                        Object param = ((MapperMethod.ParamMap) arg).get("record");
                        if (param instanceof BaseDomain) {
                            baseEntityClass = param.getClass().getSuperclass();
                            sourceParam = param;
                        }
                    } catch (BindingException e) {

                    }
                } else {
                    baseEntityClass = arg.getClass().getSuperclass();
                }
            }

            if (baseEntityClass != null) {
                // 获取当前用户
                UserSession user = null;
                try {
                    user = ContextHolder.getUserSession();
                } catch (Exception e){

                }
                if (sqlCommandType == SqlCommandType.INSERT) {
                    try {
                        Field createDate = FieldUtils.getField(sourceParam.getClass(), "createDate",true);
                        FieldUtils.writeField(createDate, sourceParam, new Date(),true);
                    } catch (Exception e) {
                        log.warn(e.getMessage(),e);
                    }
                    if(user != null){
                        try {
                            Field createId = FieldUtils.getField(sourceParam.getClass(), "createId",true);
                            FieldUtils.writeField(createId, sourceParam, user.getUserId(),true);
                        } catch (Exception e){
                            log.warn(e.getMessage(),e);
                        }
                    }

                }
                try {
                    Field createDate = FieldUtils.getField(sourceParam.getClass(), "updateDate",true);
                    FieldUtils.writeField(createDate, sourceParam, new Date(),true);
                } catch (Exception e) {
                    log.warn(e.getMessage(),e);
                }
                if(user != null){
                    try {
                        Field updateId = FieldUtils.getField(sourceParam.getClass(), "updateId",true);
                        FieldUtils.writeField(updateId, sourceParam, user.getUserId(),true);
                    } catch (Exception e){
                        log.warn(e.getMessage(),e);
                    }
                }
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {

    }
}
